package com.ruoyi.util;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @Description: 身份证效验
 * @ClassName: CardVerifi
 * @author syc
 * @date: 2022年5月25日 下午2:50:48
 */
public class CardVerifi {

	public static boolean verification(String card) {

		boolean bolStatus = numberVer(card);
		if (!bolStatus) {
			return bolStatus;
		}
		bolStatus = proNumVer(card);
		if (!bolStatus) {
			return bolStatus;
		}
		bolStatus = ageVer(card);
		if (!bolStatus) {
			return bolStatus;
		}
		card =IdentityCode_changeFivteenToEighteen(card);
		bolStatus = IdentityCode_checkParity(card);
		return bolStatus;
	}	

//	   11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林",
//       23: "黑龙江 ", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西",
//       37: "山东", 41: "河南", 42: "湖北 ", 43: "湖南", 44: "广东", 45: "广西", 46: "海南",
//       50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏 ", 61: "陕西", 62: "甘肃",
//       63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外 "

	/**
	 * @Description: 检查号码是否符合规范，包括长度，类型
	 * @author syc
	 * @date: 2022年5月26日 上午10:04:51
	 */
	public static boolean numberVer(String card) {
		String reg = "(^\\d{15}$)|(^\\d{17}(\\d|X)$)"; // 身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X
		return card.matches(reg);
	}

	/**
	 * @Description: 取身份证前两位，校验省份
	 * @author syc
	 * @date: 2022年5月26日 上午10:05:13
	 */
	public static boolean proNumVer(String card) {
		int province = Integer.parseInt(card.substring(0, 2));
		List<Integer> provinceList = Arrays.asList(11, 12, 13, 14, 15, 21, 22, 23, 31, 32, 33, 34, 35, 36, 37, 41, 42,
				43, 44, 45, 46, 50, 51, 52, 53, 54, 61, 62, 63, 64, 65, 71, 81, 82, 91);
		return provinceList.contains(province);
	}

	/**
	 * @Description: 效验年龄
	 * @author syc
	 * @date: 2022年5月26日 上午10:06:59
	 */
	@SuppressWarnings("deprecation")
	public static boolean ageVer(String card) {
		int len = card.length();
		try {
			// 身份证15位时，次序为省（3位）市（3位）年（2位）月（2位）日（2位）校验位（3位），皆为数字
			if (len == 15) {
				String year = "19" + card.substring(6, 8);
				String month = card.substring(8, 10);
				String day = card.substring(10, 12);
				Date birthday = new Date(year + '/' + month + '/' + day);
				return IdentityCode_verifyBirthday(year, month, day, birthday);
			}
			if (len == 18) {
				String year = card.substring(6, 10);
				String month = card.substring(10, 12);
				String day = card.substring(12, 14);
				Date birthday = new Date(year + "/" + month + "/" + day);
				return IdentityCode_verifyBirthday(year, month, day, birthday);
			}
			return false;
		} catch (Exception e) {
			return false;
		}

	}

	@SuppressWarnings("deprecation")
	public static boolean IdentityCode_verifyBirthday(String year, String month, String day, Date birthday) {
		Date now = new Date();
		int now_year = DateUtil.getYear(now);
		// 年月日是否合理
		if (DateUtil.getYear(birthday) == Integer.parseInt(year) && (birthday.getMonth() + 1) == Integer.parseInt(month)
				&& birthday.getDate() == Integer.parseInt(day)) {
			// 判断年份的范围（3岁到150岁之间)
			int time = now_year - Integer.parseInt(year);
			if (time >= 3 && time <= 150) {
				return true;
			}
			return false;
		}
		return false;
	}

	// 校验位的检测
	public static boolean IdentityCode_checkParity(String card) {
		card = IdentityCode_changeFivteenToEighteen(card); // 15位转18位
		int len = card.length();
		if (len == 18) {
			// arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
			// arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
			List<Integer> listnum = Arrays.asList(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
			List<String> listStr = Arrays.asList("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2");
			int cardTemp = 0;
			for (int i = 0; i < 17; i++) {
				cardTemp += Integer.parseInt(card.substring(i, i + 1)) * listnum.get(i);
			}
			String valnum = listStr.get(cardTemp % 11);
			System.out.println("cardTemp:" + cardTemp + ".....cardTemp % 11:...." + (cardTemp % 11));
			System.out.println("valnum:" + valnum);
			if (valnum.equals(card.substring(17, 18))) {
				return true;
			}
			return false;
		}
		return false;
	}


	// 15位身份证号转18位

	public static String IdentityCode_changeFivteenToEighteen(String card) {
		if (card.length() == 15) {
			List<Integer> listnum = Arrays.asList(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
			List<String> listStr = Arrays.asList("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2");
			int cardTemp = 0;
			card = card.substring(0, 6) + "19" + card.substring(6, card.length() - 6);
			for (int i = 0; i < 17; i++) {
				cardTemp += Integer.parseInt(card.substring(i, i + 1)) * listnum.get(i);
			}
			card += listStr.get(cardTemp % 11);
			return card;
		}
		return card;
	}

	/**
	 * @Author Mr.Wang
	 * @Description 将18位身份证号转化为15位返回,非18位身份证号原值返回
	 * @Param IdCard 18位身份证号
	 * @return 15身份证
	 **/
	public static String get15Ic(String IdCard) {
		String retId = "";
		if (null == IdCard) {
			return retId;
		}
		if (IdCard.length() == 18) {
			retId = IdCard.substring(0, 6) + IdCard.substring(8, 17);
		} else {
			return IdCard;
		}
		return retId;
	}

	/**
	 * @Author Mr.Wang
	 * @Description 将15位身份证号转化为18位返回，非15位身份证号原值返回
	 * @Param IdCard 18位身份证号
	 * @return 18位身份证
	 **/
	public static String get18Ic(String IdCard) {
		String retId = "";
		String id17 = "";
		int sum = 0;
		int y = 0;
		// 定义数组存放加权因子（weight factor）
		int[] wf = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
		// 定义数组存放校验码（check code）
		String[] cc = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
		if (IdCard.length() != 15) {
			return IdCard;
		}
		// 加上两位年19
		id17 = IdCard.substring(0, 6) + "19" + IdCard.substring(6);
		// 十七位数字本体码加权求和
		for (int i = 0; i < 17; i++) {
			sum = sum + Integer.valueOf(id17.substring(i, i + 1)) * wf[i];
		}
		// 计算model
		y = sum % 11;
		// 通过model得到对应的校验码 cc[y]
		retId = id17 + cc[y];
		return retId;
	}

	/**
	 * @Author Mr.Wang
	 * @Description 根据身份证解析性别(分15和18位)
	 * @Param
	 **/
	public static String getSexFromIdCard(String idCard) {
		Integer a = null;
		switch (idCard.length()) {
		case 15:
			a = Integer.parseInt(idCard.substring(14, 15)); // 取倒数第1位
			break;
		case 18:
			a = Integer.parseInt(idCard.substring(16, 17)); // 取倒数第2位
			break;
		}
		if (a % 2 == 0) { // 偶数为女性,基数为男性
			return "2";
		} else {
			return "1";
		}
	}
	
	/**
	 * @Description: 验证身份证号是否合法
	 * @author syc
	 * @date: 2022年12月2日 下午2:55:12
	 */
//	public static void main(String[] args) {
//		System.out.println(CardVerifi.IdentityCode_checkParity("410103198903138308"));
//	}
 
}
